package cn.autumnorange.app.common.repository;

import cn.autumnorange.app.common.core.IDTypeService;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.Type;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public interface AbstractPersisTableRepository<I extends Serializable> extends IDTypeService<I> {
    String ROWS = "rows";
    String TOTAL = "total";
    /**
     * 获取EntityManager
     *
     * @return
     */
    EntityManager getEntityManager();

    <T> T save(T entity);

    <T> T update(T entity);

    <T> T findById(Class<T> clazz, I id);


    /**
     * 根据表名，字段，参数查询，拼接sql语句
     *
     * @param clazz 表实体
     * @param filed 字段名
     * @param o     字段参数
     * @return
     */
    <T> List<T> findByFiled(Class<T> clazz, String filed, Object o);

    /**
     * 多个字段的查询
     *
     * @param clazz         表实体
     * @param linkedHashMap 将你的字段传入map中
     * @return
     */
    <T> List<T> findByFileds(Class<T> clazz, LinkedHashMap<String, Object> linkedHashMap);

    <T> List<T> findAll(Class<T> clazz);

    /**
     * 不分页
     */
    <T> List<T> findByNativeQuery(
            String sql, Map<String, Object> conditionParams, ResultTransformer resultTransformer, Map<String, Type> scalar);

    /**
     * 一个字段的分页
     *
     * @param clazz    表实体
     * @param filed    字段名
     * @param o        字段参数
     * @param pageNo   第几页
     * @param pageSize 一个页面多少条数据
     * @return
     */
    <T> List<T> findPageByQueryFiled(
            Class<T> clazz, String filed, Object o, int pageNo, int pageSize);

    /**
     * 多字段查询分页
     *
     * @param pageNo            第几页
     * @param pageSize          一个页面的条数
     * @param resultTransformer Transformer.
     * @param conditionParams
     * @return
     */
    Map<String, Object> findPageByNativeQueryFileds(
            String sql,
            Map<String, Object> conditionParams,
            ResultTransformer resultTransformer,
            Integer pageNo,
            Integer pageSize);

    /**
     * @param <T>
     * @param clazz
     * @param clazzIsNullHqlOrClazzIsNotNullSetAndWhereCondition clazz空则为hql语句 clazz不空则传where条件
     * @param conditionParams                                    where条件参数集合
     * @param valueParams                                        upd更新参数集合
     * @return
     */
    <T> int updateFileds(
            Class<T> clazz,
            String clazzIsNullHqlOrClazzIsNotNullSetAndWhereCondition,
            Map<String, Object> conditionParams,
            Map<String, Object> valueParams);

    /**
     * 只能删除持久状态的实体
     *
     * @param entity
     */
    <T> boolean remove(T entity);

    /**
     * 根据表的id删除数据
     *
     * @param clazz
     */
    <T> boolean deleteById(Class<T> clazz, I id);

    /**
     * 根据参数删除表数据
     *
     * @param clazz
     */
    <T> boolean deleteByMap(Class<T> clazz, Map paramsMap);

    /**
     * 根据参数删除表数据
     *
     * @param clazz
     */
    <T> boolean deleteByMap(Class<T> clazz, String hql, Map<String, Object> paramsMap);

    /**
     * 根据id查询
     *
     * @param t
     * @param idClass
     * @return
     */
    <T> T findByIdClass(T t, Object idClass);

    /**
     * 添加俩个实体关联的中间表实体
     *
     * @param clazz
     * @param primaryKeyName1
     * @param primaryKeyValue1
     * @param primaryKeyName2
     * @param primaryKeyValue2
     * @param createTime
     * @param <MT>
     * @return
     */
    <MT> boolean addMiddleTable(
            Class<MT> clazz,
            String primaryKeyName1,
            String primaryKeyValue1,
            String primaryKeyName2,
            String primaryKeyValue2,
            Timestamp createTime, Map<String, Type> scalar);

    <MT> MT findMiddleTable(
            Class<MT> clazz,
            String primaryKeyName1,
            String primaryKeyValue1,
            String primaryKeyName2,
            String primaryKeyValue2, Map<String, Type> scalar);

    <MT> boolean delMiddleTable(
            Class<MT> clazz,
            String primaryKeyName1,
            String primaryKeyValue1,
            String primaryKeyName2,
            String primaryKeyValue2);

    <MT> boolean updMiddleTable(
            Class<MT> clazz,
            String primaryKeyName1,
            String primaryKeyValue1,
            String primaryKeyName2,
            String primaryKeyValue2);

    // ---------------------------------first
    <T> T first(TypedQuery<T> tqSelect);

    <T> T first(Class<T> clazz, String hql);

    <T> T first(Class<T> clazz, String hql, Object arg);

    <T> T first(Class<T> clazz, String hql, Object arg, Object arg2);

    <T> T first(Class<T> clazz, String hql, Object... args);

    // ---------------------------------single
    <T> T single(Class<T> clazz, String hql);

    <T> T single(Class<T> clazz, String hql, Object arg);

    <T> T single(Class<T> clazz, String hql, Object arg, Object arg2);

    <T> T single(Class<T> clazz, String hql, Object... args);

    // ---------------------------------list
    <T> List<T> list(Class<T> clazz, String hql);

    <T> List<T> list(Class<T> clazz, String hql, Object arg);

    <T> List<T> list(Class<T> clazz, String hql, Object arg, Object arg2);

    <T> List<T> list(Class<T> clazz, String hql, Object... args);

    // ---------------------------------top
    <T> List<T> top(int top, Class<T> clazz, String hql);

    <T> List<T> top(int top, Class<T> clazz, String hql, Object arg);

    <T> List<T> top(int top, Class<T> clazz, String hql, Object arg, Object arg2);

    <T> List<T> top(int top, Class<T> clazz, String hql, Object... args);
}
